package com.ipay.utils;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;

public class AESUtils {
    /**
     * AES加密字符串
     * @param content 需要被加密的字符串
     * @param password 加密需要的密码
     * @return 密文
     */
    public static byte[] encrypt(String content, String password) {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
            kgen.init(128, new SecureRandom(password.getBytes()));// 利用用户密码作为随机数初始化出
            // 128位的key生产者
            //加密没关系，SecureRandom是生成安全随机数序列，password.getBytes()是种子，只要种子相同，序列就一样，所以解密只要有password就行
            SecretKey secretKey = kgen.generateKey();// 根据用户密码，生成一个密钥
            byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥，如果此密钥不支持编码，则返回
            // null。
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
            Cipher cipher = Cipher.getInstance("AES");// 创建密码器
            byte[] byteContent = content.getBytes("utf-8");
            cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化为加密模式的密码器
            byte[] result = cipher.doFinal(byteContent);// 加密
            return result;
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 解密AES加密过的字符串
     * @param content AES加密过过的内容
     * @param password 加密时的密码
     * @return 明文
     */
    public static byte[] decrypt(byte[] content, String password) {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
            /*SecureRandom random=SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(password.getBytes());
            kgen.init(128, random);*/
            kgen.init(128, new SecureRandom(password.getBytes()));
            SecretKey secretKey = kgen.generateKey();// 根据用户密码，生成一个密钥
            byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
            Cipher cipher = Cipher.getInstance("AES");// 创建密码器

            cipher.init(Cipher.DECRYPT_MODE, key);// 初始化为解密模式的密码器
            byte[] result = cipher.doFinal(content);
            return result; // 明文
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**将二进制转换成16进制
     * @param buf
     * @return
     */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**将16进制转换为二进制
     * @param hexStr
     * @return
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1){
            return null;
        }
        byte[] result = new byte[hexStr.length()/2];
        for (int i = 0;i< hexStr.length()/2; i++) {
            int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);
            int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }


    /**AES加密 将二进制转换成16进制
     * @param content
     * @param password
     * @return
     */
    public static String encryptParseByte2HexStr(String content, String password) {
        byte[] encrypt = encrypt(content, password);
        System.out.println("加密后的内容：" + new String(encrypt));
        //如果想要加密内容不显示乱码，可以先将密文转换为16进制
        String hexStrResult = parseByte2HexStr(encrypt);
        System.out.println("16进制的密文："  + hexStrResult);
        return hexStrResult.toString();
    }

    /**将16进制转换为二进制
     * @param hexStr
     * @return
     */
    public static String parseHexStr2Byte(String hexStr, String password) {
        System.out.println("密文:"+hexStr);
        byte[] twoStrResult = parseHexStr2Byte(hexStr);
        System.out.println("16进制密文:"+twoStrResult);
        // 16进制密文解密
        byte[] decrypt = decrypt(twoStrResult, password);
        System.out.println("16进制密文解密后的内容：" + new String(decrypt));
        return new String(decrypt);
    }


    public static String bin2Hex(String binStr) {
        StringBuffer temp = null;
        while (binStr.length() % 4 != 0) {
            temp = new StringBuffer(binStr);
            temp.insert(0, "0");
            binStr = temp.toString();
        }
        StringBuffer sb = new StringBuffer();
        int deci = 0;
        for (int i = 0; i <= binStr.length() - 4; i += 4) {
            deci = Integer.valueOf(binStr.substring(i, i + 4), 2);
            sb.append(Integer.toHexString(deci));
        }
        return sb.toString();
    }

    public static String hex2Bin(String hexStr) {
        StringBuffer sb = new StringBuffer();
        int deci = 0;
        StringBuffer temp = null;
        for (int i = 0; i < hexStr.length(); i++) {
            deci = Integer.valueOf(hexStr.charAt(i) + "", 16);
            temp = new StringBuffer(Integer.toBinaryString(deci));
            while (temp.length() < 4) {
                temp.insert(0, "0");
            }
            sb.append(temp);
        }
        return sb.toString();
    }







        public static String encrypt2(String input, String key){
            byte[] crypted = null;
            try{
                SecretKeySpec skey = new SecretKeySpec(key.getBytes(), "AES");
                Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
                cipher.init(Cipher.ENCRYPT_MODE, skey);
                crypted = cipher.doFinal(input.getBytes());
            }catch(Exception e){
                System.out.println(e.toString());
                e.printStackTrace();
            }
            return new String(crypted);
            //return new String(Base64.encodeBase64(crypted));
        }
        public static String decrypt(String input, String key){
            byte[] output = null;
            try{
                KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
                //kgen.init(128, new SecureRandom(key.getBytes()));// 利用用户密码作为随机数初始化出
                SecureRandom random=SecureRandom.getInstance("SHA1PRNG");
                random.setSeed(key.getBytes());
                kgen.init(128, random);
                // 128位的key生产者
                //加密没关系，SecureRandom是生成安全随机数序列，password.getBytes()是种子，只要种子相同，序列就一样，所以解密只要有password就行
                SecretKey secretKey = kgen.generateKey();// 根据用户密码，生成一个密钥
                byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥，如果此密钥不支持编码，则返回
                SecretKeySpec skey = new SecretKeySpec(enCodeFormat, "AES");
                Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
                cipher.init(Cipher.DECRYPT_MODE, skey);
                output = cipher.doFinal(input.getBytes("UTF-8"));
                //output = cipher.doFinal(Base64.decodeBase64(input));
            }catch(Exception e){
                System.out.println(e.toString());
                e.printStackTrace();
            }
            return new String(output);
        }







    public static void main(String[] args) throws UnsupportedEncodingException {
        String key = "vCfnB1SvPQqUDa7q0AFpqdiGOCICGT92";
        String data2 = "example";
        String data3 = "BE493732102064876B89862824DF8B0B779";
        //System.out.println(encrypt2(data2, key));
        String datahex2Bin2=hex2Bin(data3);
        System.out.println(decrypt(datahex2Bin2, key));/**/
        //System.out.println(decrypt(data3, key));


       /* String data="BE493732102064876B89862824DF8B0B779";
        String datahex2Bin=hex2Bin(data);
        System.out.println("===:"+datahex2Bin);//Unicode(UTF-8)
        byte[] decrypt = decrypt(datahex2Bin.getBytes("UTF-8"), key);
        System.out.println("16进制密文解密后的内容：" + decrypt);
        System.out.println("16进制密文解密后的内容：" + new String(decrypt));*/


        //{"data":"C720595A016037DB8D5095D48C8969923622E0C78A034818046BBC657C2FC97D1212E2C4DBD0E4FD8F0B99B668C6DEEE2D3D30EC676CC60AD642ECAA535533B78CC77CF2256362EF6BB4BA247E644CEAC6FEBE77C55B3EABAE920F95D3AA48DA1B7E581575E9C799173C4775052B348C982E8E13B5E0D613A556A1810DBF8BD9AE8138E61FA642FCB30007B6CE54B4A387994F8EB7CF596255F12D74E88F3BBA4E8FEB03B84B388165C139306B3E4C4CD26E90BFAC1B2341AF94455AC828EEABE3BCFE14AB84BEA2B952A5B103407C7029AC4BCA0F50B99C0C20A1D1C663EF5BDDFAEA39F5762CA7D2E433C5B3DBAC907373B3A4BC7E8E66C2C70E635F9ADAA3B3AAD601A8F54B6177502E7B1669E36FAEE1EE21FAA4D863B5BB84A22FECA4F85D668C3D62977DA6F405C0041A8AAE386EA86231E587C4053A95D2D3D7C47D921890AF6ECBDCBC57614B16CC70352A34E5BD9D637FA4BB67141EABB28B7806CBAC0664D8A9017A688B8041C6C967A2B86EB6FA1358A282CB7B7884D1ED5149E9BF08681BFA16454B5B85C4F674396D0F8EF0729A4EA123B789CC4E1A5C6AA62AABB2CBAAA3A7B48C83985CC5A5B2FDD224D2566E98E4C152946039890AE5451A801C2536F1ACCAD0C9DEDCEBD5D1549FED1BE5C6E205C32ADA68BC75727ED565202C583E27B095AB87EE9B40380D35A71D0DB3874103C7C76E00CA5A282F1F6074DAEF8FD0A2C8D627646B12A48F05072211D4807E6CD68317B2E238450F91A5534C275210F455ADC4663656A6DF45CA695DB3E7C98434E60B98D57C1543D257E62529FD577D4B4B39020E29786317C43B6FA9900AFCD425A75F3DD6AA06784FEBFD7F35DA8782CD4234EA1B875912C5683BAD37ED4EC01A40710B726121711E84FD9BA058B3165B9FAB99DD175A0DE3703715CCC39B3A2ACDA7A82DA3845FA246DF965D15A318AEA7A41B749D0F9ED1",
        // "errcode":0,"msg":"ok","timestamp":1514890793,"sign":"79e86082efb689e35b4bbce14a0999dc"}
        String content = "data=BE493732102064876B89862824DF8B0B779&errcode=0&msg=ok&open_key=vCfnB1SvPQqUDa7q0AFpqdiGOCICGT92&timestamp=1461644997";
        String password = "vCfnB1SvPQqUDa7q0AFpqdiGOCICGT92";
        /*String password = "2b125c12e7f2de366dc376b4d330bd01";*//*
        System.out.println("****加密之前：" + content);
        // 加密
        *//*String encryptStr = encryptParseByte2HexStr(content, password);
        System.out.println("****加密后的内容：" + new String(encryptStr));*//*

        String encryptStr="D0F20F8F191F41584A75900BC14A2CF572A757BEC8F4542E3B9DA52848317DC25FB21BADB91D0738EA7DAD5E93F8E4CF9405172FC882C2873B7B9A907C7A31913F58CA07943AC26D94298AA4FCF0F4C1CBE510E6329BE9E3A1307BBAA8B6573BDE248A7B3B83676A23926D94C7B4B2EC41CB69A522988C794027A2540557FAA0";
       *//* *//**//*String encryptStr="C720595A016037DB8D5095D48C8969923622E0C78A034818046BBC657C2FC97D1212E2C4DBD0E4FD8F0B99B668C6DEEE2D3D30EC676CC60AD642ECAA535533B78CC77CF2256362EF6BB4BA247E644CEAC6FEBE77C55B3EABAE920F95D3AA48DA1B7E581575E9C799173C4775052B348C982E8E13B5E0D613A556A1810DBF8BD9AE8138E61FA642FCB30007B6CE54B4A387994F8EB7CF596255F12D74E88F3BBA4E8FEB03B84B388165C139306B3E4C4CD26E90BFAC1B2341AF94455AC828EEABE3BCFE14AB84BEA2B952A5B103407C7029AC4BCA0F50B99C0C20A1D1C663EF5BDDFAEA39F5762CA7D2E433C5B3DBAC907373B3A4BC7E8E66C2C70E635F9ADAA3B3AAD601A8F54B6177502E7B1669E36FAEE1EE21FAA4D863B5BB84A22FECA4F85D668C3D62977DA6F405C0041A8AAE386EA86231E587C4053A95D2D3D7C47D921890AF6ECBDCBC57614B16CC70352A34E5BD9D637FA4BB67141EABB28B7806CBAC0664D8A9017A688B8041C6C967A2B86EB6FA1358A282CB7B7884D1ED5149E9BF08681BFA16454B5B85C4F674396D0F8EF0729A4EA123B789CC4E1A5C6AA62AABB2CBAAA3A7B48C83985CC5A5B2FDD224D2566E98E4C152946039890AE5451A801C2536F1ACCAD0C9DEDCEBD5D1549FED1BE5C6E205C32ADA68BC75727ED565202C583E27B095AB87EE9B40380D35A71D0DB3874103C7C76E00CA5A282F1F6074DAEF8FD0A2C8D627646B12A48F05072211D4807E6CD68317B2E238450F91A5534C275210F455ADC4663656A6DF45CA695DB3E7C98434E60B98D57C1543D257E62529FD577D4B4B39020E29786317C43B6FA9900AFCD425A75F3DD6AA06784FEBFD7F35DA8782CD4234EA1B875912C5683BAD37ED4EC01A40710B726121711E84FD9BA058B3165B9FAB99DD175A0DE3703715CCC39B3A2ACDA7A82DA3845FA246DF965D15A318AEA7A41B749D0F9ED1";
        // 解密*//*
        String decrypt2 = parseHexStr2Byte(encryptStr, password);
        System.out.println("****解密后的内容：" + new String(decrypt2));

//        byte[] decrypt = decrypt(encryptStr, password);
//        System.out.println("16进制密文解密后的内容：" + new String(decrypt));



        Map<String, String> map=new HashMap<String, String>();
        map.put("data","C720595A016037DB8D5095D48C8969923622E0C78A034818046BBC657C2FC97D1212E2C4DBD0E4FD8F0B99B668C6DEEE2D3D30EC676CC60AD642ECAA535533B78CC77CF2256362EF6BB4BA247E644CEAC6FEBE77C55B3EABAE920F95D3AA48DA1B7E581575E9C799173C4775052B348C982E8E13B5E0D613A556A1810DBF8BD9AE8138E61FA642FCB30007B6CE54B4A387994F8EB7CF596255F12D74E88F3BBA4E8FEB03B84B388165C139306B3E4C4CD26E90BFAC1B2341AF94455AC828EEABE3BCFE14AB84BEA2B952A5B103407C7029AC4BCA0F50B99C0C20A1D1C663EF5BDDFAEA39F5762CA7D2E433C5B3DBAC907373B3A4BC7E8E66C2C70E635F9ADAA3B3AAD601A8F54B6177502E7B1669E36FAEE1EE21FAA4D863B5BB84A22FECA4F85D668C3D62977DA6F405C0041A8AAE386EA86231E587C4053A95D2D3D7C47D921890AF6ECBDCBC57614B16CC70352A34E5BD9D637FA4BB67141EABB28B7806CBAC0664D8A9017A688B8041C6C967A2B86EB6FA1358A282CB7B7884D1ED5149E9BF08681BFA16454B5B85C4F674396D0F8EF0729A4EA123B789CC4E1A5C6AA62AABB2CBAAA3A7B48C83985CC5A5B2FDD224D2566E98E4C152946039890AE5451A801C2536F1ACCAD0C9DEDCEBD5D1549FED1BE5C6E205C32ADA68BC75727ED565202C583E27B095AB87EE9B40380D35A71D0DB3874103C7C76E00CA5A282F1F6074DAEF8FD0A2C8D627646B12A48F05072211D4807E6CD68317B2E238450F91A5534C275210F455ADC4663656A6DF45CA695DB3E7C98434E60B98D57C1543D257E62529FD577D4B4B39020E29786317C43B6FA9900AFCD425A75F3DD6AA06784FEBFD7F35DA8782CD4234EA1B875912C5683BAD37ED4EC01A40710B726121711E84FD9BA058B3165B9FAB99DD175A0DE3703715CCC39B3A2ACDA7A82DA3845FA246DF965D15A318AEA7A41B749D0F9ED1");
        map.put("errcode", "0");
        map.put("msg", "ok");
        map.put("timestamp", "1514890793");
        map.put("open_key",password);
        //按 ascii 码 A-z 排序
        String strtosign = "data=3304A5EC2CDEB4D12ED3338B5C01BF6B&open_id=87f46f5db1b65f0ac195285f49ee6958&open_key=0828e83720fdbe3685a7b94214af04f9&timestamp=1497957842";//MapUtils.formatUrlMap(map, false, false);
        System.out.println("=============================="+strtosign);
        //TODO 查询商户相关数据
        //sha1
        String strSHA1 = SHA1Utils.getSHA1(strtosign);
        System.out.println("============strSHA1==================013030c4532c00c14ad8b9e47f3382f9ea4a8ed1");
        System.out.println("============strSHA1=================="+strSHA1);
        //MD5
        String signstr = MD5.sign(strSHA1, "", "utf-8");
        System.out.println("================signstr==============915be5aff09f2686870e1d17e93b3542");
        System.out.println("================signstr=============="+signstr);
        System.out.println("79e86082efb689e35b4bbce14a0999dc");
        System.out.println("406571b4852680d8463e653f669fe449");
        System.out.println(signstr);
*/
    }
}
